﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Ionic.Zlib;
using LoLScrape.Inibin;

namespace LoLScrape
{
    /// <summary>
    /// Contains methods which will extract different data types from a ZipEntry reader stream
    /// </summary>
    static class ByteReader
    {
        public delegate Object ReadDelegate(CrcCalculatorStream stream);

        /// <summary>
        /// Reads an unsigned 8bit integer from the stream
        /// </summary>
        /// <param name="stream"></param>
        /// <returns>unsigned 8-bit integer</returns>
        public static Object ReadUInt8(CrcCalculatorStream stream)
        {
            return (UInt16)stream.ReadByte();
        } //end readUInt8

        /// <summary>
        /// 
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static Object ReadInt8(CrcCalculatorStream stream)
        {
            return (Int16)stream.ReadByte();
        } //end readInt8

        /// <summary>
        /// 
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static Object ReadInt16(CrcCalculatorStream stream)
        {
            byte[] bytes = new byte[2];

            bytes[0] = (byte)stream.ReadByte();
            bytes[1] = (byte)stream.ReadByte();

            return BitConverter.ToInt16(bytes, 0);
        } //end readInt16

        /// <summary>
        /// 
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static Object ReadUInt16(CrcCalculatorStream stream)
        {
            byte[] bytes = new byte[2];

            bytes[0] = (byte)stream.ReadByte();
            bytes[1] = (byte)stream.ReadByte();

            return BitConverter.ToUInt16(bytes, 0);
        } //end readUInt16

        /// <summary>
        /// 
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static Object ReadInt32(CrcCalculatorStream stream)
        {
            byte[] bytes = new byte[4];

            bytes[0] = (byte)stream.ReadByte();
            bytes[1] = (byte)stream.ReadByte();
            bytes[2] = (byte)stream.ReadByte();
            bytes[3] = (byte)stream.ReadByte();

            return BitConverter.ToInt32(bytes, 0);
        } //end readInt32

        /// <summary>
        /// 
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static Object ReadUInt32(CrcCalculatorStream stream)
        {
            byte[] bytes = new byte[4];

            bytes[0] = (byte)stream.ReadByte();
            bytes[1] = (byte)stream.ReadByte();
            bytes[2] = (byte)stream.ReadByte();
            bytes[3] = (byte)stream.ReadByte();

            return BitConverter.ToUInt32(bytes, 0);
        } //end readUInt32

        /// <summary>
        /// 
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static Object ReadSingle(CrcCalculatorStream stream)
        {
            byte[] bytes = new byte[4];

            bytes[0] = (byte)stream.ReadByte();
            bytes[1] = (byte)stream.ReadByte();
            bytes[2] = (byte)stream.ReadByte();
            bytes[3] = (byte)stream.ReadByte();

            return BitConverter.ToSingle(bytes, 0);
        } //end readDouble

        /// <summary>
        /// 
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static Object ReadChar(CrcCalculatorStream stream)
        {
            byte[] bytes = new byte[1];

            bytes[0] = (byte)stream.ReadByte();

            return BitConverter.ToChar(bytes, 0);
        } //end readUInt8

        /// <summary>
        /// 
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static Object ReadString(CrcCalculatorStream stream)
        {
            List<byte> bytes = new List<byte>();

            //Continue to read until 00 (NULL) is found.
            do
            {
            bytes.Add((byte)stream.ReadByte());
            } while (bytes[bytes.Count-1] != 0);

            return BitConverter.ToString(bytes.ToArray(), 0);
        } //end readString

        /// <summary>
        /// 
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static Object ReadSegment01(CrcCalculatorStream stream)
        {
            Segment01Item objSeg01Item = new Segment01Item();

            objSeg01Item.intValue = (Int32)ByteReader.ReadInt32(stream);

            return objSeg01Item;
        } //end ReadSegment01

        /// <summary>
        /// 
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static Object ReadSegment02(CrcCalculatorStream stream)
        {
            Segment02Item objSeg02Item = new Segment02Item();

            objSeg02Item.fltValue = (Single)ByteReader.ReadSingle(stream);

            return objSeg02Item;
        } //end ReadSegment02

        /// <summary>
        /// 
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static Object ReadSegment03(CrcCalculatorStream stream)
        {
            Segment03Item objSeg03Item = new Segment03Item();

            objSeg03Item.intValue = (Int16)ByteReader.ReadInt8(stream);

            return objSeg03Item;

            //return ((Double)((Int16)ByteReader.ReadInt8(stream))) / 10.0;
        } //end ReadSegment03

        /// <summary>
        /// 
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static Object ReadSegment04(CrcCalculatorStream stream)
        {
            Segment04Item objSeg04Item = new Segment04Item();

            objSeg04Item.intValue = (Int16)ByteReader.ReadInt16(stream);

            return objSeg04Item;
        } //end ReadSegment02

        /// <summary>
        /// 
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static Object ReadSegment05(CrcCalculatorStream stream)
        {
            Segment05Item objSeg05Item = new Segment05Item();

            objSeg05Item.intValue = (Int16)ByteReader.ReadInt8(stream);

            return objSeg05Item;
        } //end ReadSegment02

        /// <summary>
        /// 
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static Object ReadSegment07(CrcCalculatorStream stream)
        {
            Segment07Item objSeg07Item = new Segment07Item();

            objSeg07Item.B = (UInt16)ByteReader.ReadUInt8(stream);
            objSeg07Item.G = (UInt16)ByteReader.ReadUInt8(stream);
            objSeg07Item.R = (UInt16)ByteReader.ReadUInt8(stream);

            return objSeg07Item;
        } //end ReadSegment07

        /// <summary>
        /// 
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static Object ReadSegment08(CrcCalculatorStream stream)
        {
            Segment08Item objSeg08Item = new Segment08Item();

            objSeg08Item.B = (Single)ByteReader.ReadSingle(stream);
            objSeg08Item.G = (Single)ByteReader.ReadSingle(stream);
            objSeg08Item.R = (Single)ByteReader.ReadSingle(stream);

            return objSeg08Item;
        } //end ReadSegment08

        /// <summary>
        /// 
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static Object ReadSegment09(CrcCalculatorStream stream)
        {

            Segment09Item objSeg09Item = new Segment09Item();

            objSeg09Item.X = (UInt16)ByteReader.ReadUInt8(stream);
            objSeg09Item.Y = (UInt16)ByteReader.ReadUInt8(stream);

            return objSeg09Item;
        } //end ReadSegment9

        /// <summary>
        /// 
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static Object ReadSegment10(CrcCalculatorStream stream)
        {
            Segment10Item objSeg10Item = new Segment10Item();

            objSeg10Item.X = (Single)ByteReader.ReadSingle(stream);
            objSeg10Item.Y = (Single)ByteReader.ReadSingle(stream);

            return objSeg10Item;
        } //end ReadSegment10

        /// <summary>
        /// 
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static Object ReadSegment11(CrcCalculatorStream stream)
        {
            Segment11Item objSeg11Item = new Segment11Item();

            objSeg11Item.B = (UInt16)ByteReader.ReadUInt8(stream);
            objSeg11Item.G = (UInt16)ByteReader.ReadUInt8(stream);
            objSeg11Item.R = (UInt16)ByteReader.ReadUInt8(stream);
            objSeg11Item.A = (UInt16)ByteReader.ReadUInt8(stream);

            return objSeg11Item;
        } //end ReadSegment11

        /// <summary>
        /// 
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static Object ReadSegment12(CrcCalculatorStream stream)
        {
            Segment12Item objSeg12Item = new Segment12Item();

            objSeg12Item.B = (Single)ByteReader.ReadSingle(stream);
            objSeg12Item.G = (Single)ByteReader.ReadSingle(stream);
            objSeg12Item.R = (Single)ByteReader.ReadSingle(stream);
            objSeg12Item.A = (Single)ByteReader.ReadSingle(stream);

            return objSeg12Item;
        } //end ReadSegment12

    } //end ByteReader

} //end LoLScrape
